package com.basker.pisces.tx;

import java.util.function.Consumer;

import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;

public class TransactionHelper {
    /**
     * 对当前线程添加一个事务提交后的回调方法
     *
     * @param action
     */
    public static void doAfterCommit(Runnable action) {
        Assert.notNull(action, "parameter 'action' is required");
        Assert.isTrue(inTransactionScope(), "current thread is not in transactionScope");

        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                action.run();
            }
        });
    }

    /**
     * 对当前线程添加一个事务结束后（无论提交还是回滚）的回调方法
     *
     * @param consumer 接受事务状态
     * @see TransactionSynchronization#STATUS_COMMITTED
     * @see TransactionSynchronization#STATUS_ROLLED_BACK
     * @see TransactionSynchronization#STATUS_UNKNOWN
     */
    public static void doAfterCompletion(Consumer<Integer> consumer) {
        Assert.notNull(consumer, "parameter 'consumer' is required");
        Assert.isTrue(inTransactionScope(), "current thread is not in transactionScope");

        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCompletion(int status) {
                consumer.accept(status);
            }
        });
    }

    /**
     * 对当前线程添加一个事务提交前的回调方法
     *
     * @param consumer
     */
    public static void doBeforeCommit(Consumer<Boolean> consumer) {
        Assert.notNull(consumer, "parameter 'consumer' is required");
        Assert.isTrue(inTransactionScope(), "current thread is not in transactionScope");

        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void beforeCommit(boolean readOnly) {
                consumer.accept(readOnly);
            }
        });
    }

    /**
     * 当前线程是否在事务范围内
     *
     * @return
     */
    public static boolean inTransactionScope() {
        return TransactionSynchronizationManager.isActualTransactionActive()
                && TransactionSynchronizationManager.isSynchronizationActive();
    }
}
